package com.supreme.simpleserver.controller;

import com.supreme.commonboot.utils.AjaxResp;
import com.supreme.simpleserver.model.RDCache;
import com.supreme.simpleserver.model.RDBody;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.Set;

@RestController
@RequestMapping(value = "redis")
public class RedisController {

    private final RedisTemplate<String, Object> redisTemplate;
//    private final RedisTemplate<String, Object> db1RedisTemplate;

    @Autowired
    public RedisController(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    //Keys ==================================================
    @GetMapping(value = "showKeys/{keyword}")
    public AjaxResp showKeys(@PathVariable(value = "keyword") String keyword) {
        Set<String> keys = this.redisTemplate.keys(keyword);
        return new AjaxResp(keys);
    }
    //==================================================

    //String ==================================================
    @PostMapping(value = "set/{key}")
    public AjaxResp set(@PathVariable(value = "key") String key, @RequestBody RDBody bodyData) {
        this.redisTemplate.opsForValue().set(key, bodyData.getValue());
        return new AjaxResp();
    }

    @GetMapping(value = "get/{key}")
    public AjaxResp get(@PathVariable(value = "key") String key) {
        String result = (String) this.redisTemplate.opsForValue().get(key);
        return new AjaxResp(result);
    }

    @PostMapping(value = "setStr/{key}")
    public AjaxResp setStr(@PathVariable(value = "key") String key,
                           @RequestBody RDCache cache) {
        this.redisTemplate.opsForValue().set(key, cache);
        return new AjaxResp();
    }

    @GetMapping(value = "getStr/{key}")
    public AjaxResp getStr(@PathVariable(value = "key") String key) {
        RDCache result = (RDCache) this.redisTemplate.opsForValue().get(key);
        return new AjaxResp(result);
    }

    @PostMapping(value = "setStrList/{key}")
    public AjaxResp setStrList(@PathVariable(value = "key") String key, @RequestBody List<RDCache> cacheList) {
        this.redisTemplate.opsForValue().set(key, cacheList);
        return new AjaxResp();
    }

    @GetMapping(value = "getStrAll")
    public AjaxResp getStrAll(@RequestBody List<String> redisKeyList) {
        List<Object> result = this.redisTemplate.opsForValue().multiGet(redisKeyList);
        return new AjaxResp(result);
    }
    //==================================================

    //Hash ==================================================
    @PostMapping(value = "setHash/{hashKey}/{itemKey}")
    public AjaxResp setHash(@PathVariable(value = "hashKey") String hashKey,
                            @PathVariable(value = "itemKey") String itemKey,
                            @RequestBody RDCache cache) {
        this.redisTemplate.opsForHash().put(hashKey, itemKey, cache);
        return new AjaxResp();
    }

    @GetMapping(value = "getHash/{hashKey}/{itemKey}")
    public AjaxResp getHash(@PathVariable(value = "hashKey") String hashKey,
                            @PathVariable(value = "itemKey") String itemKey) {
        RDCache result = (RDCache) this.redisTemplate.opsForHash().get(hashKey, itemKey);
        return new AjaxResp(result);
    }

    @GetMapping(value = "getHashAll/{hashKey}")
    public AjaxResp getHashAll(@PathVariable(value = "hashKey") String hashKey) {
        Map<Object, Object> entries = this.redisTemplate.opsForHash().entries(hashKey);
        return new AjaxResp(entries);
    }

    @GetMapping(value = "hashKeyExist/{hashKey}/{itemKey}")
    public AjaxResp hashKeyExist(@PathVariable(value = "hashKey") String hashKey,
                                 @PathVariable(value = "itemKey") String itemKey) {
        Boolean result = this.redisTemplate.opsForHash().hasKey(hashKey, itemKey);
        return new AjaxResp(result);
    }

    @GetMapping(value = "getHashKeys/{hashKey}")
    public AjaxResp getHashKeys(@PathVariable(value = "hashKey") String hashKey) {
        Set<Object> keys = this.redisTemplate.opsForHash().keys(hashKey);
        return new AjaxResp(keys);
    }

    @GetMapping(value = "getHashValues/{hashKey}")
    public AjaxResp getHashValues(@PathVariable(value = "hashKey") String hashKey) {
        List<Object> result = this.redisTemplate.opsForHash().values(hashKey);
        return new AjaxResp(result);
    }

    @GetMapping(value = "getHashLen/{hashKey}")
    public AjaxResp getHashLen(@PathVariable(value = "hashKey") String hashKey) {
        Long result = this.redisTemplate.opsForHash().size(hashKey);
        return new AjaxResp(result);
    }
    //==================================================

    //List ==================================================
    @PostMapping(value = "setListLeft/{listKey}")
    public AjaxResp setListLeft(@PathVariable(value = "listKey") String listKey,
                                @RequestBody RDCache cache) {
        this.redisTemplate.opsForList().leftPush(listKey, cache);
        return new AjaxResp();
    }

    @PostMapping(value = "setListRight/{listKey}")
    public AjaxResp setListRight(@PathVariable(value = "listKey") String listKey,
                                 @RequestBody RDCache cache) {
        this.redisTemplate.opsForList().rightPush(listKey, cache);
        return new AjaxResp();
    }

    @GetMapping(value = "getList/{listKey}")
    public AjaxResp getList(@PathVariable(value = "listKey") String listKey,
                            @RequestParam(value = "start", defaultValue = "0") long start,
                            @RequestParam(value = "stop", defaultValue = "-1") long stop) {
        List<Object> cacheList = this.redisTemplate.opsForList().range(listKey, start, stop);
        return new AjaxResp(cacheList);
    }

    @GetMapping(value = "getIndex/{listKey}")
    public AjaxResp getIndex(@PathVariable(value = "listKey") String listKey,
                             @RequestParam(value = "index", defaultValue = "0") long index) {
        RDCache cache = (RDCache) this.redisTemplate.opsForList().index(listKey, index);
        return new AjaxResp(cache);
    }

    @GetMapping(value = "getLen/{listKey}")
    public AjaxResp getLen(@PathVariable(value = "listKey") String listKey) {
        Long size = this.redisTemplate.opsForList().size(listKey);
        return new AjaxResp(size);
    }

    @PutMapping(value = "updateIndex/{listKey}/{index}")
    public AjaxResp updateIndex(@PathVariable(value = "listKey") String listKey,
                                @PathVariable(value = "index") long index,
                                @RequestBody RDCache cache) {
        this.redisTemplate.opsForList().set(listKey, index, cache);
        RDCache result = (RDCache) this.redisTemplate.opsForList().index(listKey, index);
        return new AjaxResp(result);
    }

    @DeleteMapping(value = "deleteIndex/{listKey}/{index}")
    public AjaxResp deleteIndex(@PathVariable(value = "listKey") String listKey,
                                @PathVariable(value = "index") long index,
                                @RequestBody RDCache cache) {
        Long remove = this.redisTemplate.opsForList().remove(listKey, index, cache);
        return new AjaxResp(remove);
    }
    //==================================================

    //Set ==================================================
    @PostMapping(value = "setSet/{setKey}")
    public AjaxResp setSet(@PathVariable(value = "setKey") String setKey,
                           @RequestBody RDCache cache) {
        this.redisTemplate.opsForSet().add(setKey, cache);
        return new AjaxResp();
    }

    @GetMapping(value = "getSet/{setKey}")
    public AjaxResp getSet(@PathVariable(value = "setKey") String setKey) {
        Set<Object> cacheSet = this.redisTemplate.opsForSet().members(setKey);
        return new AjaxResp(cacheSet);
    }
    //==================================================

    //ZSet ==================================================
    @PostMapping(value = "setZet/{zetKey}/{score}")
    public AjaxResp setZet(@PathVariable(value = "zetKey") String zetKey,
                           @PathVariable(value = "score") double score,
                           @RequestBody RDCache cache) {
        this.redisTemplate.opsForZSet().add(zetKey, cache, score);
        return new AjaxResp();
    }

    @GetMapping(value = "getZet/{zetKey}")
    public AjaxResp getZet(@PathVariable(value = "zetKey") String zetKey,
                           @RequestParam(value = "start", defaultValue = "0") long start,
                           @RequestParam(value = "stop", defaultValue = "-1") long stop) {
        Set<Object> cacheSet = this.redisTemplate.opsForZSet().range(zetKey, start, stop);
        return new AjaxResp(cacheSet);
    }
    //==================================================

    //Bitmap ==================================================
    @PostMapping(value = "setBit/{key}/{offset}")
    public AjaxResp setBit(@PathVariable(value = "key") String key,
                           @PathVariable(value = "offset") Long offset,
                           @RequestBody RDBody bodyData) {
        final Boolean result = this.redisTemplate.opsForValue().setBit(key, offset, bodyData.getEnabled());
        return new AjaxResp(result);
    }

    @GetMapping(value = "getBit/{key}/{offset}")
    public AjaxResp getBit(@PathVariable(value = "key") String key,
                           @PathVariable(value = "offset") Long offset) {
        final Boolean result = this.redisTemplate.opsForValue().getBit(key, offset);
        return new AjaxResp(result).raw();
    }

    @GetMapping(value = "bitCount/{key}")
    public AjaxResp bitCount(@PathVariable(value = "key") String key) {
        final Long bitCount = this.redisTemplate.execute((RedisCallback<Long>) redisConnection -> redisConnection.bitCount(key.getBytes()));
        return new AjaxResp(bitCount).raw();
    }
    //==================================================
}
